package saves.objects;

import game.Units;
import images.ImageInfo;
import images.ObjectLoader;
import math.Point;
import org.jbox2d.callbacks.RayCastCallback;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Fixture;
import saves.Area;
import saves.EntidadeNave;

/**
 *
 * @author Luan Nico
 */
public final class Laser {
    private Vec2 start, direction, end;
    private float power, angle;
    private int type;
    private EntidadeNave source;
    
    public static final float[] ENERGY_COSTS = { .2f, .05f, 1f }, DAMAGE = { .03f, .01f, .5f };    
    private static final int[] IMAGES = { 0, 1, 2 };
    private static final int MAX_LENGTH = 10000;
    
    private Laser() {}
    
    public Laser(Vec2 start, float angle, int type, float power, EntidadeNave source) {
        this.start = start;
        this.end = null;
        this.rotate(angle);       
        
        this.type = type;
        this.power = power;
        this.source = source;
    }
    
    public void update(int delta, Area area) {
        RayCast rc = new RayCast();
        area.getWorld().raycast(rc, start, direction);
        
        this.end = rc.getPoint();
        if (this.end != null) { //hit something
            if (rc.getF().getBody().getUserData() instanceof Corpo) //it is a Body
                ((Corpo) rc.getF().getBody().getUserData()).harm(DAMAGE[type] * power, EntidadeNave.DamageType.HEAT, source);
        }
    }
    
    public void move(float x, float y) {
        this.start.x = x;
        this.start.y = y;
    }
    
    public void rotate(float angle) {
        this.direction = new Vec2(start.x + (float) Math.cos(angle)*MAX_LENGTH, start.y + (float) Math.sin(angle)*MAX_LENGTH);
        this.angle = ((float) Math.toDegrees(angle) + 90) % 360; //convert to luan's system
    }
    
    public float getEnergyCost() {
        return ENERGY_COSTS[type];
    }
    
    public boolean is(int type) {
        return this.type == type;
    }
    
    public void draw(float dx, float dy) {
        int h  = -MAX_LENGTH;
        if (end != null)
            h = -Units.getPixelSize(Point.dist(start.x, start.y, end.x, end.y));
        
        int ox = Units.getPixelSize(start.x) - (int) dx, oy = Units.getPixelSize(start.y) - (int) dy;
        ImageInfo.rotate(angle, ox, oy);
        ObjectLoader.drawLaser(IMAGES[type], ox - 1, oy, 3, h);
        ImageInfo.rotate(-angle, ox, oy);
    }

    private static class RayCast implements RayCastCallback {
        private Fixture f;
        private Vec2 point;
        
        @Override
        public float reportFixture(Fixture fixture, Vec2 point, Vec2 normal, float fraction) {
            this.f = fixture;
            this.point = point;
            return fraction;
        }

        public Fixture getF() {
            return f;
        }

        public Vec2 getPoint() {
            return point;
        }
    }
}
